#include "register.h"
#include "token.h"

int create_salt(unsigned char*salt) {//创建盐值
    const char charset[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    srand(time(NULL));  // 初始化随机种子（不够安全！）
    strcpy((char*)salt, "$6$");
    for (int i = 3; i < 31; i++) {
        salt[i] = charset[rand() % (sizeof(charset) - 1)];
    }
    salt[31] = '\0';

    printf("salt=%s\n",salt);
    return 0;
}

int create_encrypt(unsigned char*salt,char*password,unsigned char*digest){//创建密文
    unsigned char combined[32+8];
    memcpy(combined, password, 8);
    memcpy(combined + 8, salt, 32);

    // 计算SHA-256哈希
    SHA256(combined, 32+8, digest);

    return 0;
}

int get_user_id(MYSQL *db, const char *username) {
    char query[256];
    MYSQL_RES *result;
    MYSQL_ROW row;
    int user_id = -1;  // 默认返回-1表示未找到

    // 构建查询语句
    snprintf(query, sizeof(query),
             "SELECT id FROM users WHERE username = '%s' AND isDelete = 0",
             username);

    // 执行查询
    if (mysql_query(db, query)) {
        fprintf(stderr, "查询失败: %s\n", mysql_error(db));
        return -1;
    }

    // 获取结果集
    result = mysql_store_result(db);
    if (result == NULL) {
        fprintf(stderr, "存储结果失败: %s\n", mysql_error(db));
        return -1;
    }

    // 处理结果
    if ((row = mysql_fetch_row(result)) != NULL) {
        user_id = atoi(row[0]);  // 将字符串形式的ID转为整数
    }

    // 释放结果集
    mysql_free_result(result);

    return user_id;
}

int tackle_register(int socket, MYSQL *db, TLV_t *TLV_RECV) {
    printf("register,tlv_recv->value=%s\n",TLV_RECV->value);
    int user_id = -1;
    TLV_t* TLV_T = (TLV_t *)malloc(sizeof(TLV_t));
    memset(TLV_T, 0, sizeof(TLV_t));
    char token[65]={0};
    // 1. 解析用户名和密码（各8字节）
    char username[9] = {0};
    char password[9] = {0};
    memcpy(username, TLV_RECV->value, 8);
    memcpy(password, TLV_RECV->value + 8, 8);
printf("Username=%s,password=%s\n",username,password);
    // 2. 检查用户名是否已存在
    MYSQL_STMT *stmt = mysql_stmt_init(db);
    const char *query = "SELECT id FROM users WHERE username = ? AND isDelete = 0";
    mysql_stmt_prepare(stmt, query, strlen(query));

    MYSQL_BIND param = {0};
    param.buffer_type = MYSQL_TYPE_STRING;
    param.buffer = username;
    param.buffer_length = 8;
    mysql_stmt_bind_param(stmt, &param);

    if (mysql_stmt_execute(stmt) || mysql_stmt_store_result(stmt)) {
        fprintf(stderr, "查询失败: %s\n", mysql_stmt_error(stmt));
        goto cleanup;
    }

    if (mysql_stmt_num_rows(stmt) > 0) {
        TLV_T->type = 0xFF; // 用户名已存在
        user_id = -2;
        goto cleanup;
    }
    mysql_stmt_close(stmt);

    // 3. 生成盐值和密码哈希
    unsigned char salt[32];
    unsigned char hash[SHA256_DIGEST_LENGTH];
    create_salt(salt);
    create_encrypt(salt, password, hash);

    // 4. 插入新用户（使用预处理语句）
    stmt = mysql_stmt_init(db);
    query = "INSERT INTO users (username, password, saltNum, ciphertext,isLoggedIn) VALUES (?, ?, ?, ?,0)";
    mysql_stmt_prepare(stmt, query, strlen(query));

    MYSQL_BIND params[4] = {0};
    params[0].buffer_type = MYSQL_TYPE_STRING;
    params[0].buffer = username;
    params[0].buffer_length = 8;

    params[1].buffer_type = MYSQL_TYPE_STRING;
    params[1].buffer = password; // 明文密码（实际应只存哈希）
    params[1].buffer_length = 8;

    params[2].buffer_type = MYSQL_TYPE_BLOB;
    params[2].buffer = salt;
    params[2].buffer_length = 32;

    params[3].buffer_type = MYSQL_TYPE_BLOB;
    params[3].buffer = hash;
    params[3].buffer_length = SHA256_DIGEST_LENGTH;

    mysql_stmt_bind_param(stmt, params);
    if (mysql_stmt_execute(stmt)) {
        fprintf(stderr, "注册失败: %s\n", mysql_stmt_error(stmt));
        goto cleanup;
    }

    user_id = mysql_stmt_insert_id(stmt); // 获取新用户ID
    char uid[30] = {0};
    sprintf(uid,"%s",user_id);
    getToken(uid,token);                       //
    strncpy(TLV_T->token,token,65);
    strncpy(TLV_T->username,username,9);
    TLV_RECV->id=user_id;
    TLV_T->type = 0x30; // 注册成功
    printf("token=%s,id=%d,username=%s,传输长度为%d\n",TLV_T->token,TLV_T->id,TLV_T->username,TLV_T->length);

cleanup:
    if (user_id <= 0) TLV_T->type = 0xFF;
    sendTlv(socket, TLV_T);
    if (stmt) mysql_stmt_close(stmt);
    free(TLV_T);
    return user_id;
}

int tackle_signin(int socket, MYSQL *db,TLV_t *TLV_RECV){
    printf("已进入登陆函数\n");
    int user_id = 0;
    TLV_t* TLV_T = (TLV_t*)malloc(sizeof(TLV_t));
    memset(TLV_T, 0, sizeof(TLV_t));

    MYSQL_RES *result = NULL;
    MYSQL_ROW row;
    char token[65]={0};
    // 1. 解析接收到的TLV数据
    char username[9] = {0};
    char password[9] = {0};

    for(int i = 0; i < 8; i++) {
        username[i] = TLV_RECV->value[i];
        password[i] = TLV_RECV->value[i+8];
    }
    username[8] = '\0';
    password[8] = '\0';

    printf("登录尝试 - 用户名: %s\npassword=%s\n", username,password);

    char query[256];
    snprintf(query, sizeof(query),
             "SELECT id, saltNum, ciphertext FROM users "
             "WHERE username = '%s' AND isDelete = 0",
             username);
    TLV_T->type=0xFF;
    //在数据库中筛选用户名相同，但未被删除的命令
    if (mysql_query(db, query)) {
        fprintf(stderr, "查询失败: %s\n", mysql_error(db));
        user_id = -3;

        goto cleanup;
    }

    result = mysql_store_result(db);
    if (result == NULL){
        fprintf(stderr, "存储结果失败: %s\n", mysql_error(db));
        user_id = -3;

        goto cleanup;
    }

    // 3. 检查用户是否存在
    if (mysql_num_rows(result) == 0) {
        printf("用户不存在或已被删除\n");
        TLV_T->type = 0xFF; // 用户不存在
        TLV_T->length = 0;
        user_id = -2;
        goto cleanup;
    }

    // 4. 获取用户数据
    row = mysql_fetch_row(result);
    if (row == NULL) {
        fprintf(stderr, "获取行数据失败\n");
        user_id = -2;
        goto cleanup;
    }

    user_id = atoi(row[0]);

    unsigned char*  salt =(unsigned char*)calloc(1,128);
    salt =(unsigned char*) row[1];
    const char* stored_ciphertext = row[2];

    // 5. 验证密码
    unsigned char computed_digest[SHA256_DIGEST_LENGTH];
    create_encrypt(salt, password, computed_digest);
    if (memcmp(computed_digest, stored_ciphertext,32) != 0) {
        printf("密码错误\n");
        TLV_T->type = 0xFF; // 密码错误
        TLV_T->length = 15;
        snprintf(TLV_T->value, 20,"password error");
        user_id = -3;
        goto cleanup;
    }

    // 6. 检查用户是否已登录
    snprintf(query, sizeof(query),
             "SELECT isLoggedIn FROM users WHERE id = %d",
             user_id);

    if (mysql_query(db, query)) {
        fprintf(stderr, "查询登录状态失败: %s\n", mysql_error(db));
        user_id = -3;

        goto cleanup;
    }

    mysql_free_result(result);
    result = mysql_store_result(db);

    if (result && mysql_num_rows(result) > 0) {
        row = mysql_fetch_row(result);
        if (row && atoi(row[0]) == 1) {
            printf("用户已登录\n");
            TLV_T->type = 0xFF; // 用户已登录
            TLV_T->length = 30;
            snprintf(TLV_T->value, 30,"client has signed in");
            user_id = -4;
            goto cleanup;
        }
    }

    // 7. 更新登录状态
    snprintf(query, sizeof(query),
             "UPDATE users SET isLoggedIn = 1 WHERE id = %d",
             user_id);

    if (mysql_query(db, query)) {
        fprintf(stderr, "更新登录状态失败: %s\n", mysql_error(db));
        user_id = -4;

        goto cleanup;
    }

    // 8. 登录成功
    printf("用户 %s 登录成功, ID: %d\n", username, user_id);
    TLV_T->type = 0x30; // 登录成功
    TLV_T->length = 0;
    char uid[30] = {0};
    sprintf(uid,"%s",user_id);
    getToken(uid,token);                       //
    strncpy(TLV_T->token,token,65);
    strncpy(TLV_T->username,username,9);
    TLV_RECV->id=user_id;
    printf("token=%s,id=%d,username=%s,传输长度为%d\n",TLV_T->token,TLV_T->id,TLV_T->username,TLV_T->length);

    sendTlv(socket, TLV_T);
    if (result != NULL) {
        mysql_free_result(result);
    }


cleanup:
    if(TLV_T->type==0xFF)
        sendTlv(socket,TLV_T);
    free(TLV_T);
    printf("结束返回值user_id=%d\n",user_id);
    return user_id;

}

